local type,tostring,select,pairs=type,tostring,select,pairs
local string_rep,string_match,string_format,string_find,string_byte=
	  string.rep,string.match,string.format,string.find,string.byte

require'zdc.fieldutil'
local dfskey=zdc.fieldutil.dfskey
module(..., package.seeall)

local function serialize(data)
	local data_type = type(data)
	if data_type == "boolean" then
		return tostring(data)
	elseif data_type == "number" then
		return string_format('%.16g',data)
	elseif data_type ~= "string" then
		return string_format("nil -- Could not serialize '%s'", tostring(data))
	end

	if string_find(data,"%z") then return string_format("%q", data) end
	-- if the string contains any newlines, find a version of long quotes that will work
	if string_find(data,"\n") then
		local count = 0
		if string_byte(data,#data)==93 then count=1 end
		local rec=string_rep("=", count)
		local open = string_format("[%s[", rec)
		local close = string_format("]%s]", rec)

		while string_find(data,open, nil, true) or string_find(data,close, nil, true) do
			count = count + 1
			rec=string_rep("=", count)
			open = string_format("[%s[", rec)
			close = string_format("]%s]", rec)
		end

		return string_format("%s%s%s", open, data, close)
	else
		return string_format("%q", data)
	end
end
local lua51_keywords =
{
  ["and"] = true,    ["break"] = true,  ["do"] = true,
  ["else"] = true,   ["elseif"] = true, ["end"] = true,
  ["false"] = true,  ["for"] = true,    ["function"] = true,
  ["if"] = true,     ["in"] = true,     ["local"] = true,
  ["nil"] = true,    ["not"] = true,    ["or"] = true,
  ["repeat"] = true, ["return"] = true, ["then"] = true,
  ["true"] = true,    ["until"] = true,  ["while"] = true
}

local function _converttabkey(key)
	if type(key)=='number' then
		return '_T[' .. key .. ']'
	end
	if not lua51_keywords[key] and string_match(key, "^[%a_][%a%d_]*$") then return key end
	--local n1=string.byte(key,1) or 0
	--if (n1<48 or n1 >57) and not string_find(key,'[^%w_]') then return key end
	return '_T[' .. string_format("%q", key) .. ']'
end

local function searchfd(fields,dyfields,k)
	return (fields and fields[k]) or (dyfields and  dfskey(dyfields,k))
end
function deflate_node(node,fields,dyfields)
	local keysort={}
	local keyfd1={}
	-- Sort the keys of the node so output is consistent
	for k,v in pairs(node) do
		local fd=searchfd(fields,dyfields,k)
		if fd and fd.vir then
			--not save for vir fields
			--print("VIR field not save",k)
		else
			if fd and fd[1] then keyfd1[k]=fd[1] end
			keysort[#keysort+1]=k
		end
	end
	table.sort(keysort, function(x, y)
							if keyfd1[x] and keyfd1[y] then
								return (keyfd1[x]) < (keyfd1[y])
							else
								if type(x) == type(y) then return x < y end
								return tostring(x) < tostring(y)
							end
						end)
	local sttemp={}
	for idx=1,#keysort do
		local key = keysort[idx]
		local padded_key = _converttabkey(key)
		local value = serialize(node[key])
		sttemp[#sttemp+1] = padded_key .. '=' .. value
	end

	return table.concat(sttemp,'\n')
end

function deflate_node_cp(node,fields,dyfields)
	local cp={}
	-- Sort the keys of the node so output is consistent
	for k,v in pairs(node) do
		local ty=type(v)
		if ty == "boolean" or ty=='number' or ty=='string' then
			cp[k]=v
			
		else
			cp[k]=string_format("nil -- Could not serialize '%s'", tostring(data))
		end
	end
	return cp
end
